﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using System.Linq;

// Version: 0.0.0 
// Date: 20081230
// Basic functionality to open '.sla' file and display its content
// 
// Version 0.0.1
// Date: 20090101
// Added
// - Scroll bar
// - Tool bar
// - Status bar
//
// Version 0.0.2
// Date: 20090103
// Fixed
// - Inverted signals
// - Remove of old version during installation
// - Do not display header and checksum bytes
// Added
// - Display settings from .sla file in toolbar
// - Display current file in titlebar next to program name
// - Display current cursor position as time
// - Zoom in steps 100, 200, 400 and 800%
//
// Version 0.0.3
// Date: 20090103
// Fixed displayed time of cursor position not correct when zoomed
//
//  Version 0.0.4
// Date: 20090104
// Added
// - Settings dialog with trigger mode, sampling frequency, COM port, trigger channel and trigger edge
//
// Version 0.0.5
// Date: 200901##
// Added
// - Settings dialog: trigger modes and trigger levels per channel
// - Indexer added to SampledData class for access to sample data bytes
// - Merged RS232 communication code from Joep to acquire data
// - Communication in the background
//
// TODO
// - Save and Save As functionality
// - Vertical cursor line
// - Auto line height
// - About dialog
// - Preferences dialog with background and lines colors
// - Merge Joeps Protocol Analysis code

namespace LogicProtocolAnalyzer
{
    public partial class MainForm : Form
    {
        internal const string Title = "Protocol/Logic Analyzer";
        private const string UndefinedFilename = "Undefined";

        private Settings _settings;
        private SettingsForm _settingsForm;

        public MainForm()
        {
            InitializeComponent();

            analyzerControl.BackColor = Color.Black;
            analyzerControl.Pen = new Pen(Color.LimeGreen);

            analyzerControl.MouseMove += new MouseEventHandler(analyzerControl_MouseMove);
            analyzerControl.MouseLeave += new EventHandler(analyzerControl_MouseLeave);
            analyzerControl.ZoomFactorHandler += new ZoomFactor(analyzerControl_ZoomFactorHandler);

            toolStripStatusLabelZoomFactor.Text = "100%";

            _settings = new Settings();
            _settings.Load();
            string[] portNames = _settings.PortNames;
            if (portNames.Length == 0)
            {
                MessageBox.Show("Acquire button disabled, no COM-port found.", Title);
                toolStripButtonAcquire.Enabled = false;
                acquireToolStripMenuItem.Enabled = false;
            }

            _backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker_ProgressChanged);
            _backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker_RunWorkerCompleted);
            _backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
        }

        private void OpenFile()
        {
            if (_openFileDialog.ShowDialog(this) == DialogResult.OK)
            {
                try
                {
                    FileStream fileStream = new FileStream(_openFileDialog.FileName, FileMode.Open, FileAccess.Read, FileShare.Read);

                    analyzerControl.LoadSampleData(fileStream);

                    this.Text = string.Format("{0} - {1}", Path.GetFileName(_openFileDialog.FileName), Title);

                    toolStripTextBoxSettings.Text = string.Format("Settings: {0}", analyzerControl.SampleData.Settings);
                }
                catch (Exception exception)
                {
                    this.Text = Title;
                    string caption = "Could not open file";
                    if (!string.IsNullOrEmpty(_openFileDialog.FileName))
                    {
                        caption += " '" + _openFileDialog.FileName + "'";
                    }
                    MessageBox.Show(exception.Message, caption);
                }
            }
        }

        #region Event Handlers
        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFile();
        }

        private void acquireToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // Check for COM-port selected
            if (string.IsNullOrEmpty(_settings.PortName))
            {
                MessageBox.Show("No COM-port selected. Please specify a COM-port in the settings dialog.", Title);
                return;
            }

            if (!_settings.PortNames.Contains(_settings.PortName))
            {
                string message = string.Format("The selected COM-port '{0}' does not exist on this system. Please select a different COM-port in the settings dialog.", _settings.PortName);
                MessageBox.Show(message, Title);
                return;
            }

            this.Text = string.Format("{0} - {1}", UndefinedFilename, Title);

            toolStripButtonAcquire.Enabled = false;
            acquireToolStripMenuItem.Enabled = false;

            toolStripButtonStop.Enabled = true;
            stopToolStripMenuItem.Enabled = true;

            _backgroundWorker.RunWorkerAsync(_settings);
        }

        private void stopToolStripMenuItem_Click(object sender, EventArgs e)
        {
            _backgroundWorker.CancelAsync();
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            throw new NotImplementedException();

            //FileStream fileStream = null; // TODO
            //analyzerControl.Save(fileStream);
        }

        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            throw new NotImplementedException();

            //FileStream fileStream = null; // TODO
            //analyzerControl.Save(fileStream);
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        //private void zoomInToolStripMenuItem_Click(object sender, EventArgs e)
        //{
        //    analyzerControl.ZoomIn();
        //}

        //private void zoomOutToolStripMenuItem_Click(object sender, EventArgs e)
        //{
        //    analyzerControl.ZoomOut();
        //}

        private void toolStripMenuItemZoom_Click(object sender, EventArgs e)
        {
            if (sender as ToolStripMenuItem == toolStripMenuItemZoom100 ||
                sender as ToolStripMenuItem == toolStripMenuItemZoom100Procent)
            {
                analyzerControl.Zoom(1);

                toolStripMenuItemZoom100.Checked = true;
                toolStripMenuItemZoom100Procent.Checked = true;

                toolStripMenuItemZoom200.Checked = false;
                toolStripMenuItemZoom200Procent.Checked = false;
                toolStripMenuItemZoom400.Checked = false;
                toolStripMenuItemZoom400Procent.Checked = false;
                toolStripMenuItemZoom800.Checked = false;
                toolStripMenuItemZoom800Procent.Checked = false;
            }
            else if (sender as ToolStripMenuItem == toolStripMenuItemZoom200 ||
                sender as ToolStripMenuItem == toolStripMenuItemZoom200Procent)
            {
                analyzerControl.Zoom(2);

                toolStripMenuItemZoom100.Checked = false;
                toolStripMenuItemZoom100Procent.Checked = false;

                toolStripMenuItemZoom200.Checked = true;
                toolStripMenuItemZoom200Procent.Checked = true;

                toolStripMenuItemZoom400.Checked = false;
                toolStripMenuItemZoom400Procent.Checked = false;
                toolStripMenuItemZoom800.Checked = false;
                toolStripMenuItemZoom800Procent.Checked = false;
            }
            else if (sender as ToolStripMenuItem == toolStripMenuItemZoom400 ||
                sender as ToolStripMenuItem == toolStripMenuItemZoom400Procent)
            {
                analyzerControl.Zoom(4);

                toolStripMenuItemZoom100.Checked = false;
                toolStripMenuItemZoom100Procent.Checked = false;
                toolStripMenuItemZoom200.Checked = false;
                toolStripMenuItemZoom200Procent.Checked = false;

                toolStripMenuItemZoom400.Checked = true;
                toolStripMenuItemZoom400Procent.Checked = true;

                toolStripMenuItemZoom800.Checked = false;
                toolStripMenuItemZoom800Procent.Checked = false;
            }
            else if (sender as ToolStripMenuItem == toolStripMenuItemZoom800 ||
                sender as ToolStripMenuItem == toolStripMenuItemZoom800Procent)
            {
                analyzerControl.Zoom(8);

                toolStripMenuItemZoom100.Checked = false;
                toolStripMenuItemZoom100Procent.Checked = false;
                toolStripMenuItemZoom200.Checked = false;
                toolStripMenuItemZoom200Procent.Checked = false;
                toolStripMenuItemZoom400.Checked = false;
                toolStripMenuItemZoom400Procent.Checked = false;

                toolStripMenuItemZoom800.Checked = true;
                toolStripMenuItemZoom800Procent.Checked = true;
            }
        }

        private void settingsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if(_settingsForm == null)
            {
                _settingsForm = new SettingsForm();
            }
            _settingsForm.Settings = _settings;
            _settingsForm.Show();
            _settingsForm.Activate();
        }

        void analyzerControl_ZoomFactorHandler(int zoomFactor)
        {
            toolStripStatusLabelZoomFactor.Text = string.Format("{0}%", zoomFactor * 100);
        }

        void analyzerControl_MouseMove(object sender, MouseEventArgs e)
        {
            toolStripStatusLabelMousePosition.Text = analyzerControl.GetTime(e.X).PrettyPrintTime();
        }

        void analyzerControl_MouseLeave(object sender, EventArgs e)
        {
            toolStripStatusLabelMousePosition.Text = string.Empty;
        }

        void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker backgroundWorker = sender as BackgroundWorker;
            analyzerControl.Acquire(backgroundWorker, e);
        }

        void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            toolStripButtonStop.Enabled = false;
            stopToolStripMenuItem.Enabled = false;

            toolStripButtonAcquire.Enabled = true;
            acquireToolStripMenuItem.Enabled = true;

            toolStripProgressBar.Value = 0;

            analyzerControl.SetAutoScrollMinSize();
            analyzerControl.Invalidate();

            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message, "Failed to acquire data from analyzer");
            }
            if (e.Cancelled)
            {
                this.Text = Title;
                toolStripTextBoxSettings.Text = string.Empty;
            }
            else
            {
                this.Text = string.Format("{0} - {1}", UndefinedFilename, Title);
                toolStripTextBoxSettings.Text = string.Format("Settings: {0}", analyzerControl.SampleData.Settings);
            }
        }

        void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            toolStripProgressBar.Value = e.ProgressPercentage;
        }
        #endregion Event Handlers
    }
}
